define(function(require){
    var $ = require('jquery');
    var Uploader = function(selector,config){
        var defaultConfig = {
            name: 'userfile',
            autoUpload: true,
            states: true,
            actionUrl: '',
            signRequestEnabled: false,
            signHeader: '',
            defaultSuccessCodes: [200, 201]
        };

        var self = this;
        $.extend(this,$.extend(defaultConfig,config));
        //self.callParent();
        this.$rootElement = $(selector);
        self.buildTarget();
        this.$loadingElement = self.buildLoadingElement();
        this.target.addEventListener('change',function(){
            self.onChanged.apply(self, arguments);
        });
        this.$rootElement.on('click',function(){
            self.onButtonClick.apply(self, arguments);
        });
        self.changeState('browse');
    };

    Uploader.prototype.buildTarget = function(){
        if(this.$rootElement.css('position') != 'absolute') {
            this.$rootElement.css({position:'relative'});
        }
        var targetTpl = '<form style="position:absolute;top:-3px;right:-3px;bottom:-3px;left:-3px;"><input type="file" name="userfile" tabindex="-1" style="overflow:hidden;cursor: pointer;opacity:0;position: relative;z-index:10000;width:100%;height:100%;"></form>';

        var $target = $(targetTpl).appendTo(this.$rootElement);
        this.target = $target.find('input').get(0);
        this.formElement =  $target.get(0);

    };

    Uploader.prototype.buildLoadingElement = function(){
        var loadingEleTpl = '<span style="display:none"></span>';
        return $(loadingEleTpl).appendTo(this.$rootElement);
    };


    Uploader.prototype.onButtonClick = function(){
        console.log('button click');
        var self = this;
        if (self.currentState == 'ready') {
                var file = this.target.files[0];
                self.fireEvent('onUploadstart', {file:file});
                self.changeState('uploading');
                self.doUpload(file);
        }
    };

    Uploader.prototype.onChanged = function(e){
        debugger;
        var self = this;
        if (e.target.files.length > 0) {
            self.fireEvent('onFileSelected', {file:e.target.files[0]});
            self.changeState('ready');
        } else {
            alert('File selected but not accessible');
            self.changeState('browse');
        }
    };

    Uploader.prototype.changeState = function(state) {
        var self = this;
        self.currentState = state;
        switch (state) {
            case 'browse':
                self.$loadingElement.hide();
                self.reset();
                break;
            case 'ready':
                self.$loadingElement.hide();
                $(self.target).hide();
                if (self.autoUpload == true) {
                    self.onButtonClick();
                }
                break;
            case 'loading':
                self.$loadingElement.show();
        }
    };

    Uploader.prototype.getDefaultSuccessCodes = function(file) {
         return [1,2,3];
    };

    Uploader.prototype.parseResponse = function(response) {
        return JSON.parse(response.responseText);
    };

    Uploader.prototype.doUpload = function(file) {
        var self = this;
        var http = new XMLHttpRequest();
        if (http.upload && http.upload.addEventListener) {
            http.upload.onprogress = function(e) {
                if (e.lengthComputable) {
                    var percentComplete = (e.loaded / e.total) * 100;
                    //self.fireEvent('onProgress',{percentComplete:percentComplete.toFixed(0) + '%'});
                }
            };
            http.onreadystatechange = function (e) {
                if (this.readyState === 4) {
                    if(Array.prototype.indexOf.call(self.getDefaultSuccessCodes(),parseInt(this.status)) != -1) {
                        var response = me.parseResponse(this);
                        if (response && response.success) {
                            self.fireEvent('onSuccess', {response:response,originalevent:e});
                        } else if (response && response.message) {
                            self.fireEvent('onError', {response:response,originalevent:e});
                        } else {
                            response.message = "Unknow error";
                            self.fireEvent('onError', {response:response,originalevent:e});
                        }
                    } else {
                        self.fireEvent('onError', {status:this.status,originalevent:e});
                    }
                    self.changeState('browse');
                }
            };
            http.upload.onerror = function(e) {
                self.fireEvent('onError', {status:this.status,statusText:this.statusText,originalevent:e});
            };
        }
        http.open('POST', self.actionUrl);
        if (self.signRequestEnabled == true) {
            self.signRequest(http, function(http) {
                http.send(self.getForm(file));
            });
        } else {
            http.send(self.getForm(file));
        }
    };


    Uploader.prototype.getForm = function(file) {
        var form = new FormData();
        form.append(this.name, file);
        return form;
    };

    Uploader.prototype.reset = function() {
        var self = this;
        self.formElement.reset();
        $(self.target).show();
    };

    Uploader.prototype.signRequest = function(http, callback) {
        var self = this;
        var header = self.getSignHeader();

        if (!header) {
            self.fireEvent('onError', {'msg':"'Request signing header is not defined'"});
        }

        self.signProvider(
            function(token) {
                http.setRequestHeader(header, token);
                callback(http);
            },
            function(failureText) {
                self.fireEvent('onError', {msg:'Request signing is failed! ' + failureText});
            });
    };

    Uploader.prototype.signProvider = function(success, failure) {
        success('default-token');
    };
    Uploader.prototype.fireEvent = function(name,params) {
        console.log('fireEvent:' + name  + "params:" + JSON.stringify(params));
    };
    return Uploader;
});